package tgeo.common;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoService;
import org.apache.mina.common.IoServiceConfig;
import org.apache.mina.common.IoServiceListener;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.transport.socket.nio.DatagramAcceptor;
import org.apache.mina.transport.socket.nio.DatagramAcceptorConfig;
//import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

public class UDPServer {
	private static class DaemonThreadFactory implements ThreadFactory {
		  public Thread newThread(Runnable r) {
		      Thread t = Executors.defaultThreadFactory().newThread(r);
		      t.setDaemon(true);
		      return t;
		  }
	}

	IoAcceptor acceptor = null;
	ExecutorService executor = null;
	IoHandler handler = null;
//	SocketAcceptorConfig cfg = null;
	DatagramAcceptorConfig cfg = null;
	public void Accept(){
		ThreadFactory daemonThreadFactory = new DaemonThreadFactory();
		executor = Executors
				.newSingleThreadExecutor(daemonThreadFactory);
		acceptor = new DatagramAcceptor();
		cfg = new DatagramAcceptorConfig();
//		cfg = new SocketAcceptorConfig();
//		cfg.setReuseAddress(true);
		cfg.getFilterChain()
				.addLast("threadPool", new ExecutorFilter(executor));
		acceptor.addListener(new IoServiceListener(){

			@Override
			public void serviceActivated(IoService arg0, SocketAddress arg1,
					IoHandler arg2, IoServiceConfig arg3) {
			}

			@Override
			public void serviceDeactivated(IoService arg0, SocketAddress arg1,
					IoHandler arg2, IoServiceConfig arg3) {
			}

			@Override
			public void sessionCreated(IoSession session) {
				System.out.println("session created:" + session.hashCode());
				System.out.println("local addr:" + session.getLocalAddress());
				System.out.println("remote addr:" + session.getRemoteAddress());
			}

			@Override
			public void sessionDestroyed(IoSession session) {
				System.out.println("session closed:" + session.hashCode());
			}
			
		});		
		
		
	}
	public void Bind(int port, IoHandler handler)throws Exception{
		acceptor.bind(new InetSocketAddress(port), handler, cfg);
	}	
	public void UnBind(int port){
		acceptor.unbind(new InetSocketAddress(port));
	}

	public void Shutdown(){
		acceptor.unbindAll();
		executor.shutdown();		
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		IoHandler handler = new IoHandler(){
			@Override
			public void exceptionCaught(IoSession arg0, Throwable arg1)
					throws Exception {
			}

			@Override
			public void messageReceived(IoSession session, Object message)
					throws Exception {
				ByteBuffer buf = (ByteBuffer) message;
				byte[] bytearr = new byte[buf.remaining()];
				buf.get(bytearr);
				System.out.println(new String(bytearr));
			}

			@Override
			public void messageSent(IoSession arg0, Object arg1)
					throws Exception {
			}

			@Override
			public void sessionClosed(IoSession arg0) throws Exception {
			}

			@Override
			public void sessionCreated(IoSession arg0) throws Exception {
			}

			@Override
			public void sessionIdle(IoSession arg0, IdleStatus arg1)
					throws Exception {
			}

			@Override
			public void sessionOpened(IoSession arg0) throws Exception {
			}
			
		};
		UDPServer serv = new UDPServer();
		serv.Accept();
		try {
			serv.Bind(1234, handler);
			serv.Bind(1235, handler);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//serv.Shutdown();
	}

}
